package com.mh.common;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mh.dto.vo.R;
import com.mh.utils.JWTUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;

/**
 * JWT认证拦截器
 * 统一处理接口的JWT token验证
 * 
 * @author zmh
 */
@Component
@Slf4j
public class JwtAuthenticationInterceptor implements HandlerInterceptor {

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String requestURI = request.getRequestURI();
        String method = request.getMethod();
        
        // 处理OPTIONS预检请求（CORS）
        if ("OPTIONS".equals(method)) {
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }
        
        // 获取token
        String token = request.getHeader(JWTUtils.header);
        if (token == null || token.isEmpty()) {
            log.warn("请求缺少token，URI: {}", requestURI);
            writeErrorResponse(response, "请先登录");
            return false;
        }

        // 验证token（JWTUtils.validateToken会自动处理token前缀）
        String subject = JWTUtils.validateToken(token);
        if (subject == null || subject.isEmpty()) {
            log.warn("token验证失败，URI: {}", requestURI);
            writeErrorResponse(response, "token无效或已过期，请重新登录");
            return false;
        }

        // 将用户信息存入request，供后续使用
        request.setAttribute("userId", subject);
        return true;
    }

    /**
     * 写入错误响应（统一返回R格式）
     */
    private void writeErrorResponse(HttpServletResponse response, String message) {
        try {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            
            R<String> errorResponse = R.errorToken(message);
            String json = objectMapper.writeValueAsString(errorResponse);
            
            PrintWriter writer = response.getWriter();
            writer.write(json);
            writer.flush();
        } catch (Exception e) {
            log.error("写入错误响应失败", e);
        }
    }
}

